#include "defines.h"
#include "lib0.h"
#include "netlib.h"
#include "lib.h" /* puts等が必要 */

void print_IP(const uint8 buf[])
{
    int i;
    for (i = 0; i < 4; i++) {
        if (i) puts(".");
        putval(buf[i], 0);
    }
}

void print_MAC(const uint8 buf[])
{
    int i;
    for (i = 0; i < 6; i++) {
        if (i) puts(":");
        putxval(buf[i], 2);
    }
}

uint16 ip_checksum(uint8 *data, uint16 size)
{
    uint16 i;
    uint32 sum = 0;

    if (size) {
        for (i = 0; i < size - 1; i += 2) {
            sum += ((uint16)data[i] << 8) + data[i+1];
            sum = (sum & 0xffff) + (sum >> 16);
        }

        if (i == size - 1) { // 奇数データ長の場合
            sum += (uint16)data[i] << 8;
            sum = (sum & 0xffff) + (sum >> 16);
        }
    }

    return ~(uint16)sum;
}

int parse_IP(uint8 *buf, const char *str)
{
    char a[4];
    uint8 b[4];
    int i, j;
    const char *p = str;

    for(j = 0;;) {
        for (i = 0; i < 3; i++, p++) {
            if ('0' <= *p && *p <= '9') {
                a[i] = *p;
            } else {
                break;
            }
        }
        if (i == 0) return -1;
        a[i] = '\0';

        i = atoi(a);
        if (0 <= i && i <= 0xff) {
            b[j] = i;
        } else {
            return -1;
        }

        if (j < 3 && *p == '.') {
            j++;
            p++;
        } else if (j == 3 && *p == '\0') {
            break;
        } else {
            return -1;
        }
    }

    memcpy(buf, b, 4);
    return 0;
}

int is_loopback_address(const uint8 IP[])
{
    return IP[0] == 127;
}

uint16 udp_checksum(uint8 *data, uint16 size, uint8 *src_IP, uint8 *dst_IP)
{
    uint16 i;
    uint32 sum = 0;

    sum += ((uint32)src_IP[0] << 8) + src_IP[1];
    sum = (sum & 0xffff) + (sum >> 16);
    sum += ((uint32)src_IP[2] << 8) + src_IP[3];
    sum = (sum & 0xffff) + (sum >> 16);
    sum += ((uint32)dst_IP[0] << 8) + dst_IP[1];
    sum = (sum & 0xffff) + (sum >> 16);
    sum += ((uint32)dst_IP[2] << 8) + dst_IP[3];
    sum = (sum & 0xffff) + (sum >> 16);
    sum += 17;
    sum = (sum & 0xffff) + (sum >> 16);
    sum += size;
    sum = (sum & 0xffff) + (sum >> 16);

    if (size) {
        for (i = 0; i < size - 1; i += 2) {
            sum += ((uint16)data[i] << 8) + data[i+1];
            sum = (sum & 0xffff) + (sum >> 16);
        }

        if (i == size - 1) { // 奇数データ長の場合
            sum += (uint16)data[i] << 8;
            sum = (sum & 0xffff) + (sum >> 16);
        }
    }

    i = (uint16)sum;
    return (i == 0xffff) ? i : ~i; // i == 0はありえない
}
